package com.atguigu.dga230301.governance.assess.storage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.dga230301.governance.assess.Assessor;
import com.atguigu.dga230301.governance.bean.AssessParam;
import com.atguigu.dga230301.governance.bean.GovernanceAssessDetail;
import com.atguigu.dga230301.meta.bean.TableMetaInfo;
import com.atguigu.dga230301.meta.constant.MetaConst;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

@Component("TABLE_SIMILAR")
public class TableSimilarAssess extends Assessor {
    @Override
    protected void assessor(GovernanceAssessDetail governanceAssessDetail, AssessParam assessParam) throws ParseException {
        //0.创建Set集合用来存放相似表的表名
        HashSet<String> similarSet = new HashSet<>();


        //分析：要求两个表字段重复超过阈值，则给0分否则10分
        //首先获取到要考评表的所有字段 TableMetaInfo （表名 层级  字段）
        //然后获取到其他所有的表（同层的表）字段 （其他表的TableMetaInfo 表名 层级 字段）
        //思路：收获取到要考评的表 然后拿着这个表去查数据库一一比对  问题所在每考评一张表都要查询一次数据库
        //思路二：获取到要考评的表 然后一次性查询出考评的库中所有的表


        //1.获取要考评表的表名库名（全表名）  TableMetaInfo 所有的字段
        TableMetaInfo curTableMetaInfo = assessParam.getTableMetaInfo();

        String curFullTableName = curTableMetaInfo.getSchemaName() + "." + curTableMetaInfo.getTableName();

        //获取当前表的所有字符串类型的字段
        String curColNameJson = curTableMetaInfo.getColNameJson();

        //将所哟字符串类型的字段封装为JSONObject
        List<JSONObject> curListColJsonObj = JSON.parseArray(curColNameJson, JSONObject.class);

        //获取当前表的层级
        String curDwLevel = curTableMetaInfo.getTableMetaInfoExtra().getDwLevel();

        //2.获取其他同层次单不是当前这个表的所有元数据
        Map<String, TableMetaInfo> fullTableNameToMetaInfo = assessParam.getFullTableNameToMetaInfo();

        //遍历Map集合获取到每一张表
        for (Map.Entry<String, TableMetaInfo> otherMetaInfoMap : fullTableNameToMetaInfo.entrySet()) {
            String otherFullTableName = otherMetaInfoMap.getKey();
            TableMetaInfo otherTableMetaInfo = otherMetaInfoMap.getValue();
            //获取其他表的层级
            String otherDwLevel = otherTableMetaInfo.getTableMetaInfoExtra().getDwLevel();

            //判断是否是同层的表 以及是否是当前表
            if (!otherDwLevel.equals(MetaConst.DW_LEVEL_ODS)  //不对ods层的表做考评
                    && curDwLevel.equals(otherDwLevel) //判断得是同层的表
                    && !curFullTableName.equals(otherFullTableName) //不能是当前表
            ) {
                //获取要比对表的所有字段
                String otherColNameJson = otherTableMetaInfo.getColNameJson();

                List<JSONObject> otherListColJsonObj = JSON.parseArray(otherColNameJson, JSONObject.class);

                //计数器用来记录相同字段的个数
                Integer similarCount = 0;

                //循环遍历当前表的所有字段和对比表的所有字段 然后一个字段一个字段判断是否相等
                for (JSONObject curJsonObj : curListColJsonObj) {
                    for (JSONObject otherJsonObj : otherListColJsonObj) {
                        //获取当前的字段名
                        String curClo = curJsonObj.getString("name");
                        String otherClo = otherJsonObj.getString("name");
                        if (curClo.equals(otherClo)) {
                            similarCount++;
                        }
                    }
                }

                //当前表的总字段个数
                int curAllCloCount = curListColJsonObj.size();

                BigDecimal similarCountDecimal = BigDecimal.valueOf(similarCount);
                BigDecimal curAllCloCountDecimal = BigDecimal.valueOf(curAllCloCount);

                //求相同字段的占比
                BigDecimal curRatio = similarCountDecimal.divide(curAllCloCountDecimal, 2, RoundingMode.HALF_UP).movePointRight(2);

                //获取指标中的阈值
                String metricParamsJson = assessParam.getGovernanceMetric().getMetricParamsJson();
                BigDecimal percent = JSON.parseObject(metricParamsJson).getBigDecimal("percent");

                if (curRatio.compareTo(percent)>0){
                    //有相似表
                    similarSet.add(otherFullTableName);
                }
            }
        }

        if (!similarSet.isEmpty()){
            //集合中不是空的证明有相似的表
            governanceAssessDetail.setAssessScore(BigDecimal.ZERO);
            governanceAssessDetail.setAssessProblem("存在相似表："+similarSet);
        }
    }
}
